package com.my.test.thread.conditition;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MyQueue<T> {

    // 用数组实现队列
    private Object[] items;

    // 数组当前数量
    private int count;

    // 添加元素下标
    private int addIndex;

    // 删除元素下标
    private int removeIndex;

    private Lock lock = new ReentrantLock();

    // 添加元素
    private Condition addElement = lock.newCondition();

    // get元素
    private Condition getElement = lock.newCondition();


    public MyQueue(int size) {
        items = new Object[size];
    }

    public Object[] getItems() {
        return items;
    }

    public void setItems(Object[] items) {
        this.items = items;
    }

    /**
     * @param t
     * @throws InterruptedException
     */
    public void add(T t) throws InterruptedException {
        // 获得锁确保可见性和排他性，所以count之类的操作没有用volatitle修饰
        lock.lock();
        try {
            // 元素装满了
            while (items.length == count) {
                addElement.await();
            }
            items[addIndex] = t;
            ++addIndex;
            ++count;
            // 刚好满了,要重新初始化
            if (addIndex == items.length) {
                addIndex = 0;
            }
            getElement.signal();
        } finally {
            lock.unlock();
        }
    }

    public T get() throws InterruptedException {
        lock.lock();
        try {
            // 还没有元素
            while (count == 0) {
                getElement.await();
            }
            T t = (T) items[removeIndex];

            ++removeIndex;
            --count;
            // 取到最后一个元素了
            if (items.length == removeIndex) {
                removeIndex = 0;
            }
            addElement.signal();

            return t;
        } finally {
            lock.unlock();
        }
    }


}
